package com.glory.brepda.activity.mfg;

import android.text.InputFilter;
import android.text.Spanned;
import android.view.View;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TextView;

import androidx.annotation.NonNull;

import com.glory.brepda.R;
import com.glory.brepda.base.BaseActivity;
import com.glory.brepda.callback.CustomDialogEntityCallBack;
import com.glory.brepda.entity.AdrefListQueryEntity;
import com.glory.brepda.entity.EqpInfoEntity;
import com.glory.brepda.entity.EquipMentEntity;
import com.glory.brepda.entity.ToolEntity;
import com.glory.brepda.entity.response.BaseResponseBean;
import com.glory.brepda.utils.NetUtils;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import com.google.gson.reflect.TypeToken;
import com.lzy.okgo.model.Response;
import com.pda.platform.ui.ui_pdaplatform.callback.FreeUI_CommonCallback;
import com.pda.platform.ui.ui_pdaplatform.callback.FreeUI_DialogEntityCallBack;
import com.pda.platform.ui.ui_pdaplatform.callback.FreeUI_EntityCallBack;
import com.pda.platform.ui.ui_pdaplatform.dialog.FreeUI_GeneralPop;
import com.pda.platform.ui.ui_pdaplatform.utils_public.FreeApi_DialogUtils;
import com.pda.platform.ui.ui_pdaplatform.utils_public.FreeApi_PopUtils;
import com.pda.platform.ui.ui_pdaplatform.utils_public.FreeApi_StaticMembers;
import com.pda.platform.ui.ui_pdaplatform.view.FreeUI_ClearEditText;

import org.apache.commons.lang3.StringUtils;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;

import butterknife.BindView;
import butterknife.OnClick;

public class ChangingTheScoringKnifeActivity extends BaseActivity {

    @BindView(R.id.tvTitle)
    TextView tvTitle;
    @BindView(R.id.tvBaseSubmit)
    TextView tvBaseSubmit;
    @BindView(R.id.etToolID)
    FreeUI_ClearEditText etToolID;
//    @BindView(R.id.etLotID)
//    FreeUI_ClearEditText etLotID;
    @BindView(R.id.etEqpWorkID)
    FreeUI_ClearEditText etEqpWorkID;
    @BindView(R.id.tvEqpWorkPosition)
    TextView tvEqpWorkPosition;
    @BindView(R.id.llMain)
    LinearLayout llMain;
    @BindView(R.id.flPositionList)
    FrameLayout flPositionList;
    @BindView(R.id.tvPosition)
    TextView tvPosition;
    @BindView(R.id.ivPositionArrow)
    ImageView ivPositionArrow;
    @BindView(R.id.etLength)
    FreeUI_ClearEditText etLength;
    @BindView(R.id.etThickNess)
    FreeUI_ClearEditText etThickNess;
    @BindView(R.id.flToolChangeMethod)
    FrameLayout flToolChangeMethod;
    @BindView(R.id.tvToolChangeMethod)
    TextView tvToolChangeMethod;
    @BindView(R.id.ivToolChangeMethod)
    ImageView ivToolChangeMethod;
    @BindView(R.id.flAbnormalCause)
    FrameLayout flAbnormalCause;
    @BindView(R.id.tvAbnormalCause)
    TextView tvAbnormalCause;
    @BindView(R.id.ivAbnormalCause)
    ImageView ivAbnormalCause;
    @BindView(R.id.etKnifeLife)
    FreeUI_ClearEditText etKnifeLife;
    @BindView(R.id.etMachineLength)
    FreeUI_ClearEditText etMachineLength;
    @BindView(R.id.llError)
    LinearLayout llError;

    // 文本框输入提示
    // 旧刀寿命或旧刀更换时厚度 输入提示框，因换刀的类型显示不同的文本。默认是按照原来的文本显示
    // 划片刀：旧刀寿命；成品切割刀：旧刀更换时厚度
    TextView tvKnifeLife;

    private FreeUI_GeneralPop mPositionPop;
    private List<String> mPositionList;
    private FreeUI_GeneralPop mToolChangeMethodPop;
    private ArrayList<String> mToolChangeMethodList = new ArrayList<>();
    private FreeUI_GeneralPop mAbnormalCausePop;
    private ArrayList<String> mAbnormalCauseList = new ArrayList<>();
    // 划片刀换刀填入数值管控
    private HashMap<String, KnifeRange> knifeRangeControlMap;
    // 划片刀数值管控误差范围
    private final Double diff = 0.01;

    @Override
    protected int getLayoutResId() {
        return R.layout.activity_changing_the_scoring_knife;
    }

    @Override
    protected void initView() {
        String title = getIntent().getStringExtra(FreeApi_StaticMembers.SHOW_PLUGIN_KEY);
        tvTitle.setText(title);
        mPositionList = new ArrayList<>();
        setMainLayout(llMain);
        initEdit(etEqpWorkID, new editTextListener() {
            @Override
            public void onTextChangeListener(String s) {

                FreeUI_EntityCallBack<BaseResponseBean<EqpInfoEntity>> callBack = new CustomDialogEntityCallBack<BaseResponseBean<EqpInfoEntity>>
                        ("正在查询设备信息", new TypeToken<BaseResponseBean<EqpInfoEntity>>() {
                        }.getType(), getSupportFragmentManager(), ChangingTheScoringKnifeActivity.this) {

                    @Override
                    public void onSuccess(Response<BaseResponseBean<EqpInfoEntity>> response) {
                        super.onSuccess(response);
                        if (response.body().isSuccess(ChangingTheScoringKnifeActivity.this, true, getSupportFragmentManager())) {
                            if (response.body().getResponse().getBody().getEQUIPMENT() != null) {
                                tvEqpWorkPosition.setText(response.body().getResponse().getBody().getEQUIPMENT().getLOCATION());
                            }
                            requestPositionList(s);
                            // 请求完设备信息之后，请求治具信息，确定治具更换时的管控范围
                            getToolByIdAndSetControlRange(String.valueOf(etToolID.getText()));
                        }
                    }

                    @Override
                    public void onError(Response<BaseResponseBean<EqpInfoEntity>> response) {
                        super.onError(response);
                        loadError(response.getException(), "EQPQUARY");
                    }
                };

                JsonObject map = new JsonObject();
                map.addProperty("ACTIONTYPE", "EQPBYID");
                EquipMentEntity equipMentEntity = new EquipMentEntity();
                equipMentEntity.setEQUIPMENTID(s);
                map.add("EQUIPMENT", new JsonParser().parse(new Gson().toJson(equipMentEntity)).getAsJsonObject());
                NetUtils.requestPostNet("IF.BREQUERYEQP", "Common", ChangingTheScoringKnifeActivity.this, map, callBack);

            }
        });

        // 编辑治具ID触发，查询治具信息以及治具更换时维护信息数值管控范围
        initEdit(etToolID, this::getToolByIdAndSetControlRange);

        // 初始化文本输入提示框，提示输入旧刀寿命或旧刀更换时厚度
        tvKnifeLife = findViewById(R.id.tvKnifeLife);

        // 控制数值输入框输入的小数位数
        // 换刀维护信息可以输入的小数点位数
        final int decimalDigits = 1;
        DecimalDigitsInputFilter decimalDigitsInputFilter = new DecimalDigitsInputFilter(decimalDigits);
        etLength.setFilters(new InputFilter[]{decimalDigitsInputFilter});
        etThickNess.setFilters(new InputFilter[]{decimalDigitsInputFilter});
        etKnifeLife.setFilters(new InputFilter[]{decimalDigitsInputFilter});
        etMachineLength.setFilters(new InputFilter[]{decimalDigitsInputFilter});
    }

    /**
     * 通过治具批次号获取治具信息，从而判断治具是划片刀还是成品切割刀，从而指定相关的换刀管控范围
     *
     * @param toolId 治具批次号
     */
    private void getToolByIdAndSetControlRange(String toolId) {

        // 满足有治具编号和设备ID时，才触发接口查询
        if (StringUtils.isEmpty(toolId) || StringUtils.isEmpty(etEqpWorkID.getText())) {
            return;
        }

        // 请求数据前先将数据清空掉，如果它有的话
        if (knifeRangeControlMap != null && knifeRangeControlMap.size() > 0) {
            // 清空数据，然后重新设置一下值
            knifeRangeControlMap.clear();
            // 方法从map里面找不到数据的话会自动设置一个空值进去
            setKnifeEditTextHint();
        }

        // 校验通过 则进行请求
        FreeUI_EntityCallBack<BaseResponseBean<ToolEntity>> callBack = new CustomDialogEntityCallBack<BaseResponseBean<ToolEntity>>
                (new TypeToken<BaseResponseBean<ToolEntity>>() {
                }.getType(), getSupportFragmentManager(), this) {

            @Override
            public void onSuccess(Response<BaseResponseBean<ToolEntity>> response) {
                super.onSuccess(response);
                if (response.body().isSuccess(getApplicationContext(), false, getSupportFragmentManager())) {
                    // 请求治具数据成功，可以获取到治具的相关信息，进行信息的渲染
                    List<ToolEntity> toolList = response.body().getResponse().getBody().getTOOLLIST();

                    if (toolList.size() > 0) {
                        setKnifeChangeControlRange(toolList.get(0));
                    }
                }
            }

            @Override
            public void onError(Response<BaseResponseBean<ToolEntity>> response) {
                super.onError(response);
                loadError(response.getException(), "FINDMLOTBYID");
            }
        };

        JsonObject map = new JsonObject();
        map.addProperty("ACTIONTYPE", "LOAD");
        map.addProperty("EQUIPMENTID", String.valueOf(etEqpWorkID.getText()));
        // 请求的治具批次
        List<ToolEntity> toolList = new ArrayList<>(1);
        ToolEntity toolEntity = new ToolEntity(toolId);
        toolList.add(toolEntity);
        map.add("TOOLLIST", new JsonParser().parse(new Gson().toJson(toolList)).getAsJsonArray());
        NetUtils.requestPostNet("IF.TOOLREPORT", "Common", ChangingTheScoringKnifeActivity.this, map, callBack);
    }

    /**
     * 根据划片刀的物料描述定义划片刀换刀的换刀范围
     * 包含新刀长度、新刀厚度、旧刀寿命和旧刀更换时长度
     *
     * @param tool 划片刀的相关信息，主要用的是里面的治具规格和治具描述
     */
    private void setKnifeChangeControlRange(ToolEntity tool) {

        // 治具类型：页面只能操作划片刀、成品切割刀（软刀、硬刀）
        // 查询数值范围时会传到后台帮助查询 数值管控数据
        String knifeType;

        // 判断
        // 24/6/18 901713，新增判断成品切割刀是否有定义软硬刀，PDA需要根据它来定义换刀时卡控范围
        // 成品切割刀是否有定义是硬刀还是软刀
        // 如果没有成品切割刀没有定义的话，进行反馈，让维护人员进行维护
        if ("FinishedCuttingKnife".equals(tool.getEAPPARAM())) {
            // 进行提示并且清空内容
            if (!(StringUtils.endsWith(tool.getMATERIALDESC(), "软刀") || StringUtils.endsWith(tool.getMATERIALDESC(), "硬刀"))) {
                showConfirmDialog(tool.getMATERIALDESC() + " 成品切割刀未定义软硬刀，请联系维护人员维护");
                return;
            }
            knifeType = "成品切割刀" + StringUtils.substring(tool.getMATERIALDESC(), tool.getMATERIALDESC().length() - 2, tool.getMATERIALDESC().length());
            // 24/9/7 成品切割刀旧刀数据只需要填写旧刀的长度和宽度，故这边需要修改一下输入框显示的文本（卡控还是一样），到时候报表控制一下显示就好了
            tvKnifeLife.setText("旧刀更换时厚度(μm)：");
        } else if ("ChipCutter".equals(tool.getEAPPARAM())) {
            // 划片刀
            knifeType = "划片刀";
            // 划片刀的话保持不变
            tvKnifeLife.setText("旧刀寿命(m)：");
        } else {
            showConfirmDialog(String.format("治具：%s(%s)不是划片刀或成品切割刀，不允许在此页面操作", tool.getTOOLID(), tool.getMATERIALDESC()));
            return;
        }

        // 请求划片刀管控相关信息
        FreeUI_EntityCallBack<BaseResponseBean<AdrefListQueryEntity>> callBack = new FreeUI_DialogEntityCallBack<BaseResponseBean<AdrefListQueryEntity>>
                (new TypeToken<BaseResponseBean<AdrefListQueryEntity>>() {
                }.getType(), getSupportFragmentManager(), this) {

            @Override
            public void onSuccess(Response<BaseResponseBean<AdrefListQueryEntity>> response) {
                super.onSuccess(response);
                if (response.body().isSuccess(getApplicationContext(), true, getSupportFragmentManager())) {
                    ArrayList<AdrefListQueryEntity.AdrefList> knifeControlRefList = response.body().getResponse().getBody().getADREFLIST();
                    if (knifeControlRefList.size() > 0) {
                        // 根据用户栏位参考值的大小初始化划片刀管控字典
                        knifeRangeControlMap = new HashMap<>(knifeControlRefList.size(), 1);
                        for (AdrefListQueryEntity.AdrefList ref:
                                knifeControlRefList) {

                            // 临界值，数值控制范围
                            String[] criticalValue = StringUtils.split(ref.getDESCRIPTION(), "-");
                            if (criticalValue == null || criticalValue.length != 2) {
                                showConfirmDialog(ref.getKEY() + " 划片刀设置管控范围有问题，请联系管理员");
                                return;
                            }

                            // 设置范围，ref.getTEXT()用来区分是哪一个输入框的数值范围
                            try {
                                knifeRangeControlMap.put(ref.getTEXT(), new KnifeRange(Double.parseDouble(criticalValue[0])
                                        , Double.parseDouble(criticalValue[1]), diff));
                            } catch (NumberFormatException e) {
                                showConfirmDialog(ref.getKEY() + " 划片刀设置管控范围格式有问题，应为纯数字，请联系管理员");
                                return;
                            }
                        }

                        // 各数值范围获取到之后，可以对各输入的提示信息进行设置
                        setKnifeEditTextHint();
                    }
                }
            }

            @Override
            public void onError(Response<BaseResponseBean<AdrefListQueryEntity>> response) {
                super.onError(response);
                loadError(response.getException(), "ADREFLISTQUERY");
            }
        };

        JsonObject map = new JsonObject();
        map.addProperty("REFERENCETYPE", "USER");
        map.addProperty("REFERENCENAME", "KNIFE_CHANGE_RANGE_CONTROL");
        map.addProperty("WHERECLAUSE", "KEY_ID ='" + knifeType + "'");

        NetUtils.requestPostNet("IF.ADREFLISTQUERY", "Common", ChangingTheScoringKnifeActivity.this, map, callBack);

    }

    // 如果数值范围是一个固定值，根据需求，直接将值设置在输入框上
    // 设置治具上机维护信息的提示信息，数据是在map里面，根据关键字从里面获取出来就好了
    private void setKnifeEditTextHint() {

        KnifeRange knifeRange = knifeRangeControlMap.get("NewKnifeLength");
        // 新刀长度
        etLength.setHint(Objects.toString(knifeRange, StringUtils.EMPTY));
        etLength.setText(Objects.toString(KnifeRange.getFixValue(knifeRange), StringUtils.EMPTY));

        // 新刀厚度
        knifeRange = knifeRangeControlMap.get("NewKnifeThickness");
        etThickNess.setHint(Objects.toString(knifeRange, StringUtils.EMPTY));
        etThickNess.setText(Objects.toString(KnifeRange.getFixValue(knifeRange), StringUtils.EMPTY));


        // 旧刀寿命或旧刀更换时宽度
        knifeRange = knifeRangeControlMap.get("OldKnifeLife");
        etKnifeLife.setHint(Objects.toString(knifeRange, StringUtils.EMPTY));
        etKnifeLife.setText(Objects.toString(KnifeRange.getFixValue(knifeRange), StringUtils.EMPTY));


        // 旧刀更换时长度
        knifeRange = knifeRangeControlMap.get("OldKnifeLength");
        etMachineLength.setHint(Objects.toString(knifeRange, StringUtils.EMPTY));
        etMachineLength.setText(Objects.toString(KnifeRange.getFixValue(knifeRange), StringUtils.EMPTY));
    }

    /**
     * 检查用户输入的值是否在数据管控范围里面
     * @param range 数值管控范围
     * @param tips 提示信息的开头
     * @param editText 用户输入的信息（值）
     * @return 检查通过 true，检查不通过false
     */
    private boolean checkKnifeRange(KnifeRange range, String tips, String editText) {
        if (range == null) {
            showConfirmDialog(tips + "未设置数值管控范围，请联系管理员维护");
            return false;
        }

        try {
            // 调用类的方法进行范围校验，若校验失败，则进行校验
            if(!range.isInRange(Double.parseDouble(editText))) {
                final String ERROR_MESSAGE_TEMPLATE = "%s不符合实际范围%s";
                showConfirmDialog(String.format(ERROR_MESSAGE_TEMPLATE, tips, range.toString()));
                return false;
            }
            return true;
        } catch (NumberFormatException e) {
            showToast(tips + "输入格式错误，应为纯数字", false);
            return false;
        }

    }

    private void requestPositionList(String s) {
        FreeUI_EntityCallBack<BaseResponseBean<List<String>>> callBack = new CustomDialogEntityCallBack<BaseResponseBean<List<String>>>
                (new TypeToken<BaseResponseBean<List<String>>>() {
                }.getType(), getSupportFragmentManager(), this) {

            @Override
            public void onSuccess(Response<BaseResponseBean<List<String>>> response) {
                super.onSuccess(response);
                if (response.body().isSuccess(getApplicationContext(), false, getSupportFragmentManager())) {
                    mPositionList.clear();
                    if (response.body().getResponse().getBody() == null) {
                        return;
                    }

                    mPositionList.addAll(response.body().getResponse().getBody());

                }
            }

            @Override
            public void onError(Response<BaseResponseBean<List<String>>> response) {
                super.onError(response);
                loadError(response.getException(), "GetStationByEqpId");
            }
        };
        JsonObject map = new JsonObject();
        map.addProperty("EQUIPMENTID", s);
        NetUtils.requestPostNet("GetStationByEqpId", "GetStationByEqpId", ChangingTheScoringKnifeActivity.this, map, callBack);
    }

    @Override
    protected void initData() {
        mToolChangeMethodList.add("正常换刀");
        mToolChangeMethodList.add("异常换刀");

        // 25/1/21 根据产线OA，异常换刀原因修正为：刀片破损，刀片穿孔，刀片变形，产品崩边
        mAbnormalCauseList.add("刀片破损");
        mAbnormalCauseList.add("刀片穿孔");
        mAbnormalCauseList.add("刀片变形");
        mAbnormalCauseList.add("产品崩边");
    }

    @OnClick({R.id.tvBaseSubmit, R.id.flPositionList, R.id.flToolChangeMethod, R.id.flAbnormalCause})
    public void onViewClicked(View view) {
        switch (view.getId()) {
            case R.id.tvBaseSubmit:
//                if (actionControl("Submit21")){
//                    return;
//                }

                if (getText(etEqpWorkID).equals("") || getText(etToolID).equals("")) {
                    showToast("设备号或ToolID不能为空", false);
                    return;
                }

                if(tvPosition.getText().equals("")){
                    showToast("请先选择站点!", false);
                    return;
                }

                // 检查换刀管控范围是否有正常获取到，没有获取到进行提示
                if (knifeRangeControlMap == null) {
                    showConfirmDialog("尚未获取到换刀时各填写数据的数值管控范围，请联系管理员");
                    return;
                }

                if (tvPosition.getText().toString().equals("Z1轴") || tvPosition.getText().toString().equals("Z2轴")) {
                    if (getText(etLength).equals("")) {
                        showToast("请输入新刀长度", false);
                        return;
                    }
                    if (getText(etThickNess).equals("")) {
                        showToast("请输入新刀厚度", false);
                        return;
                    }
                    if (tvToolChangeMethod.getText().toString().equals("")) {
                        showToast("请选择换刀方式", false);
                        return;
                    }

                    if (tvToolChangeMethod.getText().toString().equals("异常换刀") && tvAbnormalCause.getText().toString().equals("")) {
                        showToast("请选择异常原因", false);
                        return;
                    }
                    if (getText(etKnifeLife).equals("")) {
                        showToast("请输入旧刀寿命", false);
                        return;
                    }
                    if (getText(etMachineLength).equals("")) {
                        showToast("请输入旧刀更换时长度", false);
                        return;
                    }
                }

                // 检验是否通过所有数值范围的管控，目前需要检验：新刀长度、新刀厚度、旧刀寿命、旧刀更换时长度
                // 不通过的方法里面会有提示
                boolean notPassAllKnifeRangeCheck = !(checkKnifeRange(knifeRangeControlMap.get("NewKnifeLength"), "新刀长度", getText(etLength))
                        && checkKnifeRange(knifeRangeControlMap.get("NewKnifeThickness"), "新刀厚度", getText(etThickNess))
                        // 由于输入框tvKnifeLife是动态变化的，故提示信息改从文本框里面获取，并去除掉
                        && checkKnifeRange(knifeRangeControlMap.get("OldKnifeLife"), StringUtils.removePattern(String.valueOf(tvKnifeLife.getText()), "\\((m|μm)\\)："), getText(etKnifeLife))
                        && checkKnifeRange(knifeRangeControlMap.get("OldKnifeLength"), "旧刀更换时长度", getText(etMachineLength)));

                // 若不能通过所有校验，则返回
                if (notPassAllKnifeRangeCheck) {
                    return;
                }

                FreeApi_DialogUtils.getConfirmAndCancelDialog(this, "确定要提交?", new FreeUI_CommonCallback() {
                    @Override
                    public void onSuccess() {
                        FreeUI_EntityCallBack<BaseResponseBean<JSONObject>> callBack = new CustomDialogEntityCallBack<BaseResponseBean<JSONObject>>
                                (new TypeToken<BaseResponseBean<JSONObject>>() {
                                }.getType(), getSupportFragmentManager(), this) {

                            @Override
                            public void onSuccess(Response<BaseResponseBean<JSONObject>> response) {
                                super.onSuccess(response);
                                if (response.body().isSuccess(getApplicationContext(), false, getSupportFragmentManager())) {
                                    showToast("绑定成功", true);
                                    finish();
                                }
                            }

                            @Override
                            public void onError(Response<BaseResponseBean<JSONObject>> response) {
                                super.onError(response);
                                loadError(response.getException(), "TOOLREPORT");
                            }
                        };
//                        JsonObject map = new JsonObject();
//                        map.addProperty("ACTIONTYPE","UP");
//                        map.addProperty("EQUIPMENTID",getText(etEqpWorkID));
//                        map.addProperty("LOTID",getText(etLotID));
//                        map.addProperty("SITE",tvPosition.getText().toString());
//                        List<ToolEntity> toolList = new ArrayList<>();
//                        ToolEntity toolEntity = new ToolEntity(getText(etToolID));
//                        toolList.add(toolEntity);
//                        map.add("TOOLLIST",new JsonParser().parse(new Gson().toJson(toolList)).getAsJsonArray());
//                        NetUtils.requestPostNet("IF.TOOLREPORT","TOOLREPORT",ToolBindActivity.this,map,callBack);
                        JsonObject map = new JsonObject();
                        map.addProperty("ACTIONTYPE", "UP");
                        map.addProperty("EQUIPMENTID", getText(etEqpWorkID));
                        map.addProperty("LOTID", "划片刀换刀");
                        map.addProperty("SITE", tvPosition.getText().toString());
                        map.addProperty("LENGTH", getText(etLength));
                        map.addProperty("THICK_NESS", getText(etThickNess));
                        if (tvToolChangeMethod.getText().toString().equals("正常换刀")) {
                            tvAbnormalCause.setText("");
                        }
                        map.addProperty("TOOL_CHANGE_METHOD", tvToolChangeMethod.getText().toString());
                        map.addProperty("ABNORMAL_CAUSE", tvAbnormalCause.getText().toString());
                        map.addProperty("KNIFE_LIFE", getText(etKnifeLife));
                        map.addProperty("MACHINE_LENGTH", getText(etMachineLength));
                        List<ToolEntity> toolList = new ArrayList<>();
                        ToolEntity toolEntity = new ToolEntity(getText(etToolID));
                        toolList.add(toolEntity);
                        map.add("TOOLLIST", new JsonParser().parse(new Gson().toJson(toolList)).getAsJsonArray());
                        NetUtils.requestPostNet("CPC.TOOLREPORT", "TOOLREPORT", ChangingTheScoringKnifeActivity.this, map, callBack);
                    }
                }, () -> {

                }).show(getSupportFragmentManager(), "TOOLREPORT");
                break;
            case R.id.flPositionList:

                if (mPositionList.size() <= 0) {
                    showToast("未获取到站点列表", false);
                    return;
                }

                if (mPositionPop != null) {
                    if (mPositionPop.isShowing()) {
                        mPositionPop.dismiss();
                    }
                } else {
                    mPositionPop = FreeApi_PopUtils.getNormalPop(getApplicationContext(), flPositionList.getWidth(), mPositionList, ivPositionArrow, (codeS, i) -> {
                        tvPosition.setText(codeS);
                    });
                }
                FreeApi_PopUtils.setArrowShow(ivPositionArrow);
                mPositionPop.showAsDropDown(flPositionList, 0, 0);
                break;
            case R.id.flToolChangeMethod:
                if (mToolChangeMethodPop != null) {
                    if (mToolChangeMethodPop.isShowing()) {
                        mToolChangeMethodPop.dismiss();
                    }
                } else {
                    mToolChangeMethodPop = FreeApi_PopUtils.getNormalPop(getApplicationContext(), flToolChangeMethod.getWidth(), mToolChangeMethodList, ivToolChangeMethod, (codeS, i) -> {
                        tvToolChangeMethod.setText(codeS);
                        if (tvToolChangeMethod.getText().toString().equals("正常换刀")) {
                            llError.setVisibility(View.GONE);
                        }else{
                            llError.setVisibility(View.VISIBLE);
                        }
                    });
                }
                FreeApi_PopUtils.setArrowShow(ivToolChangeMethod);
                mToolChangeMethodPop.showAsDropDown(flToolChangeMethod, 0, 0);
                break;
            case R.id.flAbnormalCause:
                if (mAbnormalCausePop != null) {
                    if (mAbnormalCausePop.isShowing()) {
                        mAbnormalCausePop.dismiss();
                    }
                } else {
                    mAbnormalCausePop = FreeApi_PopUtils.getNormalPop(getApplicationContext(), flAbnormalCause.getWidth(), mAbnormalCauseList, ivAbnormalCause, (codeS, i) -> {
                        tvAbnormalCause.setText(codeS);
                    });
                }
                FreeApi_PopUtils.setArrowShow(ivAbnormalCause);
                mAbnormalCausePop.showAsDropDown(flAbnormalCause, 0, 0);
                break;
        }

    }

}

/**
 * 数值管控范围类
 */
class KnifeRange {
    // 最小值
    private final Double min;
    // 最大值
    private final Double max;

    // 比较值时的误差范围
    private final Double diff;

    public KnifeRange(Double min, Double max, Double diff) {
        this.min = min;
        this.max = max;
        this.diff = diff;
    }

    public boolean isInRange(Double value) {

        // 根据精度来判断value和最大或最小值是否大致相等
        if (Math.abs(value - min) < diff || Math.abs(value - max) < diff) {
            return true;
        } else {
            return value > min && value < max;
        }
    }

    /**
     * 如果治具数值范围是一个固定值（即最小值等于最大值），返回其固定值
     * @param range 数值范围
     * @return 固定值，如果是固定值则会有返回值，否则返回null
     */
    public static String getFixValue(KnifeRange range) {
        if (range == null) {
            return null;
        }

        if (Math.abs(range.getMax() - range.getMin()) < range.getDiff()) {
            return String.valueOf(range.getMin());
        }

        return null;
    }

    @NonNull
    @Override
    public String toString() {
        return min + "-" + max;
    }

    public Double getMin() {
        return min;
    }

    public Double getMax() {
        return max;
    }

    public Double getDiff() {
        return diff;
    }
}

/**
 * 治具维护信息输入框，兼数值卡控输入框，目前整数可以输入无限个，小数只能输入调用构造函数时输入的数字
 */
class DecimalDigitsInputFilter implements InputFilter {
    private final int decimalDigits;

    public DecimalDigitsInputFilter(int decimalDigits) {
        this.decimalDigits = decimalDigits;
    }

    @Override
    public CharSequence filter(CharSequence source, int start, int end,
                               Spanned dest, int dStart, int dEnd) {
        StringBuilder builder = new StringBuilder(dest);
        // 拼接字符串，拼接成即将要渲染成的字符串。
        builder.replace(dStart, dEnd, source.subSequence(start, end).toString());

        // 未来新字符串值如果是为空的话，允许其修改，不卡控
        if (StringUtils.isEmpty(builder)) {
            return null;
        }

        // 渲染成的字符串是否符合定义的正则表达式
        // 该正则表达式整数可以输入无限个，小数点之后只能输入decimalDigits定义的数量
        if (!builder.toString().matches(
                "(([0-9])+)(\\.[0-9]{0," + decimalDigits + "})?"
        )) {
            if (source.length() == 0) {
                return dest.subSequence(dStart, dEnd);
            }
            return StringUtils.EMPTY;
        }

        return null;
    }
}
